package qc.module.qms.service.exchange;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.module.qms.dto.exchange.category.ExchangeCategoryDto;
import qc.module.qms.dto.exchange.category.ExchangeCategoryStationDto;
import qc.module.qms.dto.exchange.category.ExchangeCategoryStationSetDto;
import qc.module.qms.dto.station.StationDto;
import qc.module.qms.entity.ExchangeCategory;
import qc.module.qms.entity.ExchangeCategoryStation;
import qc.module.qms.mapper.ExchangeCategoryMapper;
import qc.module.qms.repository.ExchangeCategoryRepository;
import qc.module.qms.repository.ExchangeChannelRepository;
import qc.module.qms.service.QmsStationService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * ExchangeCategoryService
 *
 * @author QuCheng Tech
 * @since 2024/1/23
 */
@Service
public class ExchangeCategoryService {
    private ExchangeCategoryRepository repository;

    @Autowired
    private ExchangeChannelRepository channelRepository;

    @Autowired
    private ExchangeCategoryStationService categoryStationService;

    @Autowired
    private QmsStationService stationService;

    @Autowired
    public void setExchangeCategoryRepository(ExchangeCategoryRepository repository) {
        this.repository = repository;
    }

    /***
     * 获取所有交换数据分类信息
     *
     * @return java.util.List<qc.module.qms.dto.exchange.category.ExchangeCategoryDto>
     * @author QuCheng Tech
     * @since 2024/1/24
     */
    public List<ExchangeCategoryDto> getAll() {
        LambdaQueryWrapper<ExchangeCategory> wrapper = new LambdaQueryWrapper<>();

        //排序，按分类名称升序
        wrapper.orderByAsc(ExchangeCategory::getName);

        //查询数据
        List<ExchangeCategory> ens = repository.selectList(wrapper);
        if (ens != null && ens.size() > 0x0) {
            return ExchangeCategoryMapper.MAPPER.toDtoList(ens);
        }

        return null;
    }

    /***
     * 根据指定的分类ID集合查询分类信息
     *
     * @param categoryIds 分类ID集合
     * @return java.util.List<qc.module.qms.dto.exchange.category.ExchangeCategoryDto>
     * @author QuCheng Tech
     * @since 2024/1/24
     */
    public List<ExchangeCategoryDto> getByFilterIds(Integer[] categoryIds) {
        //如果传入的分类ID集合为空，返回结果为空
        if (categoryIds != null && categoryIds.length > 0x0) {
            LambdaQueryWrapper<ExchangeCategory> wrapper = new LambdaQueryWrapper<>();

            //根据ID进行筛选
            //优化查询条件：如果分类ID集合只有1个使用eq条件
            if (categoryIds.length == 0x1)
                wrapper.eq(ExchangeCategory::getId, categoryIds[0x0]);
            else
                wrapper.in(ExchangeCategory::getId, categoryIds);

            //排序，按分类名称升序
            wrapper.orderByAsc(ExchangeCategory::getName);

            //查询数据
            List<ExchangeCategory> ens = repository.selectList(wrapper);
            if (ens != null && ens.size() > 0x0) {
                return ExchangeCategoryMapper.MAPPER.toDtoList(ens);
            }
        }

        return null;
    }

    /***
     * 查询指定通道ID下的分类集合
     *
     * @param channelId 通道ID
     * @return java.util.List<qc.module.qms.dto.exchange.category.ExchangeCategoryDto>
     * @author QuCheng Tech
     * @since 2024/1/24
     */
    public List<ExchangeCategoryDto> getByChannelId(int channelId) {
        LambdaQueryWrapper<ExchangeCategory> wrapper = new LambdaQueryWrapper<>();

        //根据通道ID进行筛选
        wrapper.eq(ExchangeCategory::getCid, channelId);

        //排序，按分类名称升序
        wrapper.orderByAsc(ExchangeCategory::getName);

        //查询数据
        List<ExchangeCategory> ens = repository.selectList(wrapper);
        if (ens != null && ens.size() > 0x0) {
            return ExchangeCategoryMapper.MAPPER.toDtoList(ens);
        }

        return null;
    }

    /***
     * 查询指定通道ID集合中的分类集合信息
     *
     * @param channelIds 通道ID集合
     * @return java.util.List<qc.module.qms.dto.exchange.category.ExchangeCategoryDto>
     * @author QuCheng Tech
     * @since 2024/1/24
     */
    public List<ExchangeCategoryDto> getByChannelIds(Integer[] channelIds) {
        //如果传入的通道ID集合为空，返回结果为空
        if (channelIds != null && channelIds.length > 0x0) {
            LambdaQueryWrapper<ExchangeCategory> wrapper = new LambdaQueryWrapper<>();

            //根据ID进行筛选
            //优化查询条件：如果通道ID集合只有1个使用eq条件
            if (channelIds.length == 0x1)
                wrapper.eq(ExchangeCategory::getCid, channelIds[0x0]);
            else
                wrapper.in(ExchangeCategory::getCid, channelIds);

            //排序，按分类名称升序
            wrapper.orderByAsc(ExchangeCategory::getName);

            //查询数据
            List<ExchangeCategory> ens = repository.selectList(wrapper);
            if (ens != null && ens.size() > 0x0) {
                return ExchangeCategoryMapper.MAPPER.toDtoList(ens);
            }
        }

        return null;
    }

    /***
     * 根据指定的站点编码集合获取分类集合信息
     *
     * @param stationCodes 站点编码集合
     * @return java.util.List<qc.module.qms.dto.exchange.category.ExchangeCategoryDto>
     * @author QuCheng Tech
     * @since 2024/1/24
     */
    public List<ExchangeCategoryDto> getByStationCodes(String[] stationCodes) {
        //如果传入的站点编码集合为空，返回结果为空
        if (stationCodes != null && stationCodes.length > 0x0) {
            MPJLambdaWrapper<ExchangeCategory> wrapper = new MPJLambdaWrapper<>();
            wrapper.select(ExchangeCategory::getId, ExchangeCategory::getName, ExchangeCategory::getCid, ExchangeCategory::getTablecode, ExchangeCategory::getParams);
            //join连接查询，需要关联表和关联表中的字段在前
            //wrapper.innerJoin(ExchangeCategory.class, ExchangeCategory::getId, ExchangeCategoryStation::getCid);
            wrapper.innerJoin(ExchangeCategoryStation.class, ExchangeCategoryStation::getCid, ExchangeCategory::getId);
            wrapper.in(ExchangeCategoryStation::getStcd, stationCodes);

            //排序，按通道名称升序
            wrapper.orderByAsc(ExchangeCategory::getName);

            //查询数据
            List<ExchangeCategory> ens = repository.selectJoinList(ExchangeCategory.class, wrapper);
            if (ens != null && ens.size() > 0x0) {
                return ExchangeCategoryMapper.MAPPER.toDtoList(ens);
            }
        }

        return null;
    }

    /***
     * 查询指定的分类信息
     *
     * @param categoryId 分类ID
     * @return qc.module.qms.dto.exchange.category.ExchangeCategoryDto
     * @author QuCheng Tech
     * @since 2024/1/24
     */
    public ExchangeCategoryDto get(int categoryId) {
        ExchangeCategory en = repository.selectById(categoryId);

        if (en != null)
            return ExchangeCategoryMapper.MAPPER.toDto(en);

        return null;
    }

    /***
     * 指定指定交换数据分类ID对应的数据库表名称
     *
     * @param categoryId 分类ID
     * @return qc.module.qms.dto.exchange.category.ExchangeCategoryDto
     * @author QuCheng Tech
     * @since 2024/1/24
     */
    public String getTableCode(int categoryId) {
        LambdaQueryWrapper<ExchangeCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ExchangeCategory::getTablecode);
        //根据分类ID进行筛选
        wrapper.eq(ExchangeCategory::getId, categoryId);

        ExchangeCategory en = repository.selectOne(wrapper);

        if (en != null)
            return en.getTablecode();

        return null;
    }

    /**
     * 新增
     *
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public String add(ExchangeCategoryDto dto) {
        //1.判空
        if (Objects.isNull(dto)) return QCUnifyReturnValue.Warn("新增对象不能为空");
        if (StringUtils.isBlank(dto.getName())) return QCUnifyReturnValue.Warn("数据分类名称不能为空");
        if (dto.getCid() < 0x1) return QCUnifyReturnValue.Warn("使用的通道ID不能为空");
        if (StringUtils.isBlank(dto.getTablecode())) return QCUnifyReturnValue.Warn("数据库表编码不能为空");

        //2.判断通道ID是否存在，不存在则提示
        if (Objects.isNull(channelRepository.selectById(dto.getCid())))
            return QCUnifyReturnValue.Warn("通道ID对象不存在");

        //3.判断数据库表编码是否存在，不存在则提示

        //4.DTO -> ENTITY
        ExchangeCategory en = ExchangeCategoryMapper.MAPPER.toEntity(dto);

        //5.保存数据
        if (repository.insert(en) < 0x1)
            return QCUnifyReturnValue.Warn("新增数据失败");
        return QCUnifyReturnValue.Success();
    }

    /**
     * 修改
     *
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public String update(ExchangeCategoryDto dto) {
        //1.判空
        if (Objects.isNull(dto)) return QCUnifyReturnValue.Warn("新增对象不能为空");
        if (StringUtils.isBlank(dto.getName())) return QCUnifyReturnValue.Warn("数据分类名称不能为空");
        if (dto.getCid() < 0x1) return QCUnifyReturnValue.Warn("使用的通道ID不能为空");
        if (StringUtils.isBlank(dto.getTablecode())) return QCUnifyReturnValue.Warn("数据库表编码不能为空");

        //2.判断通道ID是否存在，不存在则提示
        if (Objects.isNull(channelRepository.selectById(dto.getCid())))
            return QCUnifyReturnValue.Warn("通道ID对象不存在");

        //3.判断修改对象是否存在，不存在则提示
        if (!isExist(dto.getId())) {
            return QCUnifyReturnValue.Warn("修改的分类不存在");
        }

        //4.DTO -> ENTITY
        ExchangeCategory en = ExchangeCategoryMapper.MAPPER.toEntity(dto);

        //5.修改数据
        repository.updateById(en);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 删除
     *
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public String delete(Integer categoryId) throws QCPromptException {
        // 1.条件判空
        if (categoryId < 0x1) throw new QCPromptException("分类ID不能为空");

        //2.删除分类与站点关联关系
        categoryStationService.deleteByCid(categoryId);

        //3.删除分类信息
        repository.deleteById(categoryId);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 获取指定分类与站点的关联信息
     *
     * @param categoryId 分类ID
     * @return List<ExchangeCategoryStationDto>
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public List<ExchangeCategoryStationDto> getStations(Integer categoryId) throws QCPromptException {
        //1.查询数据分类是否存在，不存在则提示
        if (!isExist(categoryId)) throw new QCPromptException("数据分类对象不存在");

        List<ExchangeCategoryStationDto> result = new ArrayList<>();

        //2.查询所有站点信息集合，如果有站点则继续往下
        List<StationDto> stationDtos = stationService.getAll();
        if (CollectionUtils.isNotEmpty(stationDtos)) {
            //3.根据分类id查询关联站点关系集合
            Integer[] categoryIds = new Integer[1];
            Arrays.fill(categoryIds, categoryId);
            List<ExchangeCategoryStation> categoryStations = categoryStationService.getCategoryStations(categoryIds);
            //数据分类关联站点集合为空时也需要逐个站点进行遍历
            //4.循环站点集合与关联关系集合，设置每一个结果对象
            for (StationDto stationDto : stationDtos) {
                int direction = 0;
                boolean checked = false;
                //数据分类关联站点集合不为空时，判断是否已有关联
                if (CollectionUtils.isNotEmpty(categoryStations)) {
                    for (ExchangeCategoryStation categoryStation : categoryStations) {
                        if (stationDto.getStcd().equals(categoryStation.getStcd())) {
                            direction = categoryStation.getDirection();
                            checked = true;
                        }
                    }
                }
                //5.设置返回结果数据
                ExchangeCategoryStationDto dto = new ExchangeCategoryStationDto();
                dto.setStation(stationDto);
                dto.setDirection(direction);
                dto.setChecked(checked);
                result.add(dto);
            }
        }
        return result;
    }

    /**
     * 设置指定分类与站点关联关系。修改交换方向
     *
     * @param dto 请求参数对象
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/17
     */
    public String setStations(ExchangeCategoryStationSetDto dto) {
        if (Objects.isNull(dto)) return QCUnifyReturnValue.Warn("设置条件对象不能为空");
        if (dto.getId() < 0x1) return QCUnifyReturnValue.Warn("分类ID不能为空");
        if (dto.getDirection() < 0x1) return QCUnifyReturnValue.Warn("交换方向不能为空");

        //设置关联关系
        categoryStationService.addStationsByCid(dto.getId(), dto.getStcds(), dto.getDirection());

        return QCUnifyReturnValue.Success();
    }


    /**
     * 修改指定分类与站点的交换方向
     *
     * @param dto 请求参数对象
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/17
     */
    public String setStationDirection(ExchangeCategoryStationSetDto dto) {
        if (Objects.isNull(dto)) return QCUnifyReturnValue.Warn("设置条件对象不能为空");
        if (dto.getId() < 0x1) return QCUnifyReturnValue.Warn("分类ID不能为空");
        if (CollectionUtils.isEmpty(dto.getStcds())) return QCUnifyReturnValue.Warn("站点编码不能为空");
        if (dto.getDirection() < 0x1) return QCUnifyReturnValue.Warn("交换方向不能为空");

        categoryStationService.updateDirection(dto.getId(), dto.getStcds(), dto.getDirection());
        return QCUnifyReturnValue.Success();
    }

    /**
     * 判断数据分类对象是否存在
     *
     * @param cid 分类ID
     * @return 返回true表示存在，false表示不存在
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public boolean isExist(Integer cid) {
        if (Objects.nonNull(repository.selectById(cid)))
            return true;
        return false;
    }
}
